home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CD ROM Paradise Collection 4
/
CD ROM Paradise Collection 4 1995 Nov.iso
/
program
/
tjgold.zip
/
INSTALL.004
/
FGUSER10.TXT
< prev
next >
Wrap
Text File
|
1995-05-29
|
18KB
|
448 lines
Classic Menus
"If gold rust what shall iren do?"
Chaucer 1340-1400
Introduction
A classic menu is a menu displayed in a window (as shown in
figure 10.1 below). In applications that don't use a desktop (like
Quicken) the classic menu often forms the main screen of the
program. The GOLDMENU unit provides pop-up menus with the following
features:
- Automatic prefixing of options with numbers, letters or
function keys.
- Support for disabled options.
- Automatic menu placement with multiple column support.
- Full mouse support.
Figure 10.1
A Classic Menu
Basic Concepts
GOLDMENU defines the MenuRecord record as follows:
MenuRecord = record
Heading1 : string[MenuStrLength];
Heading2 : string[MenuStrLength];
Topic : array[1..MaxChoices] of string[MenuStrLength];
TotalPicks : integer;
PicksPerLine : byte;
AddPrefix : byte;
TopLeftXY : array[1..2] of byte;
Boxtype : byte;
Colors : array[1..5] of byte;
Margins : byte;
AllowEsc : boolean;
Hook : MenuHook;
HindHook : MenuHindHook;
end; {MenuRecord}
A menu record defines all the properties of the menu, i.e. the
headings, the colors, the position, the menu items, etc. The basic
approach to displaying a menu is to declare a variable of type
MenuRecord, update the record variable with the menu items,
headings etc., and call DisplayMenu to instruct Gold to display the
menu and return when the user has made a selection.
Listed below is an extract from the demo program DEMMEN1.PAS
which illustrates this basic approach:
var
MainMenu: MenuRecord;
Choice,Ecode: integer;
procedure SetMenu;
{}
begin
MenuSet(MainMenu);
with MainMenu do
begin
Heading1 := 'TechnoJock''s Turbo Toolkit';
Heading2 := 'Gold!';
Topic[1] := 'Unit Descriptions';
Topic[2] := '!Unit Demos';
Topic[3] := 'Self-Running Demo';
Topic[4] := 'How to register';
Topic[5] := 'About GOLD';
Topic[6] := '';
Topic[7] := 'Exit Demo';
TotalPicks := 7;
Boxtype := 5;
AddPrefix := 3;
PicksPerLine := 1;
AllowEsc := false;
end;
end; { SetMenu }
begin
...
SetMenu;
DisplayMenu(MainMenu,false,Choice,ECode);
...
end.
Use MenuSet First!
Important Note: Always, always, call the MenuSet function to
initialize a menu record before assigning values to the various
menu record components. MenuSet initializes all the menu record
elements to suitable default values.
Managing the MenuRecord
Listed below is a description of the main MenuRecord fields:
Heading1 - The heading at the top of the menu. Set the string
to null (the default) if you don't want a heading.
Heading2 - The second heading at the top of the menu. Set the
string to null (the default) if you don't want a heading.
Topic - An array of the actual menu items that will be
displayed in the menu. Start with the first element,
assign menu items strings to each element of the array
until you have fully defined the menu items, e.g.
Topic[1] := 'Unit Descriptions';
Topic[2] := '-Unit Demos';
Topic[3] := 'Self-Running Demo';
Topic[4] := 'How to register';
Topic[5] := 'About GOLD';
Topic[6] := '';
Topic[7] := 'Exit Demo';
TotalPicks - The total number of items in the menu. In the
above example, the value would be 7.
PicksPerLine - Identifies how many items will be displayed on
each line in the menu. Gold automatically adjusts this
setting if the text is too long to fit on the screen.
AddPrefix - Gold can automatically prefix the menu items with
numbers, letters or function keys. By default, the prefix
is zero which indicates that no prefix should be used.
The other valid settings are 1, 2, 3 and 4 as follows:
1 All menu options are prefixed with a single digit
number. If TotalPicks exceeds 9, an alpha prefix will
be used instead.
2 All menu options are prefixed with a letter, starting
with A. If TotalPicks exceeds 26, the prefix is
ignored.
3 All menu options are prefixed with a function key,
beginning with F1. If total picks exceeds 10, the Gold
will prefix with alphas instead.
4 The first capital letter in each item is highlighted
and the user can select the item by pressing the
highlighted letter.
TopLeftXY - A two byte array which identifies the X and Y
coordinate for the top left corner of the menu -- Gold
automatically determines the overall dimensions of the
menu based upon the length of headings and items. If you
specify coordinates too close to a screen edge, Gold
automatically adjusts the menu position so that it is
fully visible. When the X coordinate is set to 0, the menu
is centered horizontally on the display. Similarly, a Y
coordinate 0 will center the menu vertically. For example,
if you want the menu to be displayed in the center of the
screen starting on the seventh line, the declaration would
be:
MainMenu.TopLeftXY[1] := 0;
MainMenu.TopLeftXY[2] := 7;
BoxType - Indicates the window style, and should have a value
in the range 0 to 2 or 5, as follows:
0 No Border
1 Single Line Border
2 Double Line Border
5 Quicken-style menu
Colors - A five byte array which defines the menu display
colors. Refer to the section Customizing Menu Colors
(later) for more information.
Margins - The number of spaces separating the menu border and
the picks. Typical values range from 1 to 5.
AllowEsc - A boolean variable which controls whether the Esc
key is operative, i.e. whether or not the user can escape
from the menu. When this field is set to FALSE, the
escape key is ignored, otherwise the menu session
finishes and the Retcode is set to 1.
A Few Tips and Tricks
If a menu topic begins with the exclamation character (!), the
menu item will be inactive, i.e. grayed out.
If you want a blank line between two specific items, specify
an item in between the two using a null string -- this approach is
used in DEMMEN1.PAS on element 6.
Don't forget that the menu will be automatically centered if
the TopLeftXY[1] and TopLeftXY[2] elements are set to zero.
By default, Gold supports a maximum of 30 items in a menu. If
you need more than 30, just assign a higher value to the GOLDMENU
constant MaxChoices.
Displaying the Menu
Having called MenuSet and configured the menu record, use
DisplayMenu (defined below) to display the menu.
DisplayMenu(MenuDef: MenuRecord; Window:Boolean;
var Choice,Errorcode: integer);
Displays a classic menu. MenuDef is the menu record defining
the menu content. Set Window to true if you want the menu to be
removed when a selection is made, or false if you want the menu to
remain visible. The Choice variable is updated with the user's
selection. Error codes are returned in the ErrorCode variable.
Controlling the Default Menu Selection
The third parameter passed to DisplayMenu is a variable
integer parameter which is updated with the selection made by the
user, e.g. it will have a value of 7 if the user selects the
seventh menu option.
This variable also controls which menu item is highlighted
when the menu is first displayed. Be sure to assign an appropriate
value to the Choice variable before calling DisplayMenu.
Checking the Return Code
If the user is allowed to escape (by setting the menu record
field AllowEsc to TRUE), you will need to test the value of the
ErrorCode parameter before launching the appropriate menu
selection. If the user escaped from the menu, ErrorCode will be set
to 1, otherwise it will have a value of zero.
Customizing the Menu Colors
The default menu colors assigned to each individual menu can
be set using the GoldSetColor procedure, assigning attributes to
the following TINT elements:
MenuHiHot
MenuHi
MenuNormHot
MenuNorm
MenuBorder
The following code is an extract from DEMMEN2.PAS which
assigns custom colors to the menu defaults:
procedure CustomizeColors;
{}
begin
GoldSetColor(MenuHiHot,YellowOnGreen);
GoldSetColor(MenuHi,BlackonGreen);
GoldSetColor(MenuNormHot,YellowOnMagenta);
GoldSetColor(MenuNorm,WhiteOnMagenta);
GoldSetColor(MenuOff,LightgrayonMagenta);
GoldSetColor(MenuBorder,YellowOnMagenta);
end; { CustomizeColors }
The GoldSetColor procedure should be called prior to
initializing the menu record with MenuSet.
The technique just described controls the default colors for
all menus. You can change the colors for an individual menu by
modifying the values of the menu record's Colors array, after
initializing the record with MenuSet. Each of the five elements of
the array control the display colors of the menu as follows:
Colors[1] The highlighted item's prefix.
Colors[2] The text of the highlighted item.
Colors[3] The menu headings and the standard items prefix.
Colors[4] The text of the standard items.
Colors[5] The menu border color.
The color of non-selectable items (i.e. items which start with
the minus character) can only be altered by using the GoldSetColor
method (described above) using the MenuOff element.
Using Menu Hooks
Classic menus support two types of hooks: hind hooks and
character hooks:
Using Hind Hooks
The hind hook is called once when the menu is first displayed,
and every time a keystroke or mouse click is processed by the menu.
A hind hook is ideal for displaying a long description for the
highlighted topic.
For a procedure to be eligible as a pop-up menu hind hook it
must adhere to the following rules:
The procedure must be declared as a far procedure at the root
level. Refer to the section Understanding Hooks in Chapter 3
for further information.
The procedure must be declared with two passed parameters. The
first integer parameter indicates the active item. The second
parameter must be a variable of type integer; if this variable
is assigned a non-zero value, the menu will automatically
terminate, and the Errorcode (passed to DisplayMenu) will be
assigned the value.
The following procedure declaration follows these rules:
{$F+}
procedure LongDesc(Choice:integer; var Ecode:integer);
{Displays a long description for the highlighted topic}
var Msg: StrScreen;
begin
ClearLine(24,WhiteOnBlue);
case Choice of
1: Msg := 'Provides descriptions of each unit';
2: Msg := 'Demos showing the power of each unit';
3: Msg := 'Launches into the self-running demo';
4: Msg := 'Explains how you can register Gold';
5: Msg := 'Displays program information';
7: Msg := 'Stops the program';
end;
WriteCenter(24,UseTint,Msg);
end; { LongDesc }
{$F-}
Having written a procedure following the rules, the menu
record field HindHook should be set to the procedure, e.g.
MainMenu.HindHook := LongDesc;
The demo program DEMMEN3.PAS illustrates how to use a hind hook.
Using Character Hooks
A classic menu character hook is a procedure which is called
every time a key is pressed. The hooked procedure is called before
the key is processed, i.e. before the character is handled by
DisplayMenu. The hook is particularly useful for trapping special
keys like F1 for help, or Alt-X to exit.
For a procedure to be eligible as a pop-up menu character hook
it must adhere to the following rules:
The procedure must be declared as a far procedure at the root
level. Refer to the section Understanding Hooks in Chapter 3
for further information.
The procedure must be declared with one variable parameter of
type word, and variable of type integer, and a variable
parameter of type integer. The first parameter indicates which
key was pressed. the second parameter indicates which pick is
highlighted. If this variable is assigned a non-zero value,
the menu will automatically terminate, and the Errorcode
(passed to DisplayMenu) will be assigned the value.
The following procedure declaration follows these rules:
{$F+}
procedure CheckForKeys(var Key:word; Choice:integer;
var Ecode:integer);
{Checks for F1 or Alt-X}
begin
if Key = 315 then
.....
end; { CheckForkeys }
{$F-}
Having written a procedure following the rules, the menu
record field Hook should be set to the procedure, e.g.
MainMenu.Hook := CheckForkeys;
The demo program DEMMEN4.PAS illustrates how to use a pop-up
menu character hook.
Structuring a Menu-Driven Program
If you are writing an application which uses a Gold classic
menu as the main menu, read on.
Using a Repeat-Until Loop
DisplayMenu displays a menu and returns the value selected by
the user. If you want an application to always return to the main
menu after completing a task selected by the user, the DisplayMenu
statement must be placed in some form of loop.
Listed below is an extract from DEMMEN1.PAS which loops
continuously back to the main menu:
SetScreen;
SetMenu;
MouseShow(true);
Choice := 5;
repeat
DisplayMenu(MainMenu,false,Choice,ECode);
case Choice of
1: PromptOK(' Pretend ','Descriptions');
2: ;
3: PromptOK(' Pretend ','Self-Running Demo');
4: PromptOK(' Pretend ','How to register');
5: PromptOK(' About ','^Gold||Copyr.....');
end;
until Choice = 7;
MouseShow(false);
clrscr;
Notice that the initial value of Choice is set before the menu
is first displayed, and that the repeat loop is terminated when the
user selects option 7 -- the quit option. Also, note that the code
includes a case statement after DisplayMenu to branch to another
part of the program based on the user's selection.
That's all there is to it!
Created Nested Menus
The following extract from DEMMEN5.PAS illustrates how to
create nested menus. In this example, when a user selects item 1
from the main menu, a sub-menu of additional items is displayed.
Pressing Esc in the sub-menu will return the user back to the main
menu.
Choice := 1;
SubChoice := 1;
repeat
DisplayMenu(M1,false,Choice,ECode);
case Choice of
1: begin
repeat
DisplayMenu(MM,true,SubChoice,ECode);
if Ecode <> 0 then
SubChoice := 5;
case SubChoice of
1: ;
2: ;
{etc.}
end;
until SubChoice = 5;
end;
2..4: PromptOK(' Selection ','You chose... end;
until Choice = 5;
MouseShow(false);
clrscr;
Notice there is a nested case statement to handle separately
the main and sub-menu choices, and that different variables are
used to track the menu selections: Choice and SubChoice.